"""
***************************************************************************
    Parameters.py
    ---------------------
    Date                 : August 2012
    Copyright            : (C) 2012 by Victor Olaya
    Email                : volayaf at gmail dot com
***************************************************************************
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
***************************************************************************
"""

__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'

import sys

from qgis.core import (Qgis,
                       QgsRasterLayer,
                       QgsVectorLayer,
                       QgsMapLayer,
                       QgsCoordinateReferenceSystem,
                       QgsExpression,
                       QgsProject,
                       QgsRectangle,
                       QgsWkbTypes,
                       QgsVectorFileWriter,
                       QgsProcessing,
                       QgsProcessingUtils,
                       QgsProcessingParameters,
                       QgsProcessingParameterDefinition,
                       QgsProcessingParameterRasterLayer,
                       QgsProcessingParameterVectorLayer,
                       QgsProcessingParameterBand,
                       QgsProcessingParameterBoolean,
                       QgsProcessingParameterCrs,
                       QgsProcessingParameterRange,
                       QgsProcessingParameterPoint,
                       QgsProcessingParameterGeometry,
                       QgsProcessingParameterEnum,
                       QgsProcessingParameterExtent,
                       QgsProcessingParameterExpression,
                       QgsProcessingParameterMatrix,
                       QgsProcessingParameterFile,
                       QgsProcessingParameterField,
                       QgsProcessingParameterVectorDestination,
                       QgsProcessingParameterFileDestination,
                       QgsProcessingParameterFolderDestination,
                       QgsProcessingParameterRasterDestination,
                       QgsProcessingParameterPointCloudDestination,
                       QgsProcessingParameterString,
                       QgsProcessingParameterMapLayer,
                       QgsProcessingParameterMultipleLayers,
                       QgsProcessingParameterFeatureSource,
                       QgsProcessingParameterNumber,
                       QgsProcessingParameterColor,
                       QgsProcessingParameterPointCloudLayer,
                       QgsProcessingParameterAnnotationLayer)

from qgis.PyQt.QtCore import QCoreApplication

PARAMETER_NUMBER = 'number'
PARAMETER_DISTANCE = 'distance'
PARAMETER_SCALE = 'scale'
PARAMETER_RASTER = 'raster'
PARAMETER_TABLE = 'vector'
PARAMETER_VECTOR = 'source'
PARAMETER_STRING = 'string'
PARAMETER_EXPRESSION = 'expression'
PARAMETER_BOOLEAN = 'boolean'
PARAMETER_TABLE_FIELD = 'field'
PARAMETER_EXTENT = 'extent'
PARAMETER_FILE = 'file'
PARAMETER_POINT = 'point'
PARAMETER_GEOMETRY = 'geometry'
PARAMETER_CRS = 'crs'
PARAMETER_MULTIPLE = 'multilayer'
PARAMETER_BAND = 'band'
PARAMETER_LAYOUTITEM = 'layoutitem'
PARAMETER_MAP_LAYER = 'layer'
PARAMETER_RANGE = 'range'
PARAMETER_ENUM = 'enum'
PARAMETER_MATRIX = 'matrix'
PARAMETER_VECTOR_DESTINATION = 'vectorDestination'
PARAMETER_FILE_DESTINATION = 'fileDestination'
PARAMETER_FOLDER_DESTINATION = 'folderDestination'
PARAMETER_RASTER_DESTINATION = 'rasterDestination'
PARAMETER_POINTCLOUD_DESTINATION = 'pointCloudDestination'


def getParameterFromString(s, context=''):
    # Try the parameter definitions used in description files
    if '|' in s and (s.startswith("QgsProcessingParameter") or s.startswith("*QgsProcessingParameter") or s.startswith('Parameter') or s.startswith('*Parameter')):
        isAdvanced = False
        if s.startswith("*"):
            s = s[1:]
            isAdvanced = True
        tokens = s.split("|")
        params = [t if str(t) != str(None) else None for t in tokens[1:]]

        if True:
            clazz = getattr(sys.modules[__name__], tokens[0])
            # convert to correct type
            if clazz == QgsProcessingParameterRasterLayer:
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
            elif clazz == QgsProcessingParameterPointCloudLayer:
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
            elif clazz == QgsProcessingParameterAnnotationLayer:
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
            elif clazz == QgsProcessingParameterBand:
                if len(params) > 4:
                    params[4] = True if params[4].lower() == 'true' else False
                if len(params) > 5:
                    params[5] = True if params[5].lower() == 'true' else False
            elif clazz == QgsProcessingParameterVectorLayer:
                if len(params) > 2:
                    try:
                        params[2] = [int(p) for p in params[2].split(';')]
                    except ValueError:
                        params[2] = [getattr(QgsProcessing, p.split(".")[1]) for p in params[2].split(';')]
                if len(params) > 4:
                    params[4] = True if params[4].lower() == 'true' else False
            elif clazz == QgsProcessingParameterMapLayer:
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
                    try:
                        params[4] = [int(p) for p in params[4].split(';')]
                    except ValueError:
                        params[4] = [getattr(QgsProcessing, p.split(".")[1]) for p in params[4].split(';')]
            elif clazz == QgsProcessingParameterBoolean:
                if len(params) > 2:
                    params[2] = True if params[2].lower() == 'true' else False
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
            elif clazz == QgsProcessingParameterPoint:
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
            elif clazz == QgsProcessingParameterGeometry:
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
                if len(params) > 4:
                    try:
                        params[4] = [int(p) for p in params[4].split(';')]
                    except ValueError:
                        params[4] = [getattr(QgsWkbTypes, p.split(".")[1]) for p in params[4].split(';')]
                if len(params) > 5:
                    params[5] = True if params[5].lower() == 'true' else False
            elif clazz == QgsProcessingParameterCrs:
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
            elif clazz == QgsProcessingParameterRange:
                if len(params) > 2:
                    try:
                        params[2] = Qgis.ProcessingNumberParameterType(int(params[2]))
                    except ValueError:
                        params[2] = getattr(QgsProcessingParameterNumber, params[2].split(".")[1])
                if len(params) > 4:
                    params[4] = True if params[4].lower() == 'true' else False
            elif clazz == QgsProcessingParameterExtent:
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
            elif clazz == QgsProcessingParameterExpression:
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
            elif clazz == QgsProcessingParameterEnum:
                if len(params) > 2:
                    params[2] = params[2].split(';')
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
                if len(params) > 4:
                    # For multiple values; default value is a list of int
                    if params[3] is True:
                        params[4] = [int(v) for v in params[4].split(',')] if params[4] is not None else None
                    else:
                        params[4] = int(params[4]) if params[4] is not None else None
                if len(params) > 5:
                    params[5] = True if params[5].lower() == 'true' else False
            elif clazz == QgsProcessingParameterFeatureSource:
                if len(params) > 2:
                    try:
                        params[2] = [int(p) for p in params[2].split(';')]
                    except ValueError:
                        params[2] = [getattr(QgsProcessing, p.split(".")[1]) for p in params[2].split(';')]
                if len(params) > 4:
                    params[4] = True if params[4].lower() == 'true' else False
            elif clazz == QgsProcessingParameterMultipleLayers:
                if len(params) > 2:
                    try:
                        params[2] = Qgis.ProcessingSourceType(int(params[2]))
                    except ValueError:
                        params[2] = getattr(QgsProcessing, params[2].split(".")[1])
                if len(params) > 4:
                    params[4] = True if params[4].lower() == 'true' else False
            elif clazz == QgsProcessingParameterMatrix:
                if len(params) > 2:
                    params[2] = int(params[2])
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
                if len(params) > 4:
                    params[4] = params[4].split(';')
                if len(params) > 6:
                    params[6] = True if params[6].lower() == 'true' else False
            elif clazz == QgsProcessingParameterField:
                if len(params) > 4:
                    try:
                        params[4] = Qgis.ProcessingFieldParameterDataType(int(params[4]))
                    except ValueError:
                        params[4] = getattr(QgsProcessingParameterField, params[4].split(".")[1])
                if len(params) > 5:
                    params[5] = True if params[5].lower() == 'true' else False
                if len(params) > 6:
                    params[6] = True if params[6].lower() == 'true' else False
                if len(params) > 7:
                    params[7] = True if params[7].lower() == 'true' else False
            elif clazz == QgsProcessingParameterFile:
                if len(params) > 2:
                    try:
                        params[2] = Qgis.ProcessingFileParameterBehavior(int(params[2]))
                    except ValueError:
                        params[2] = getattr(QgsProcessingParameterFile, params[2].split(".")[1])
                if len(params) > 5:
                    params[5] = True if params[5].lower() == 'true' else False
            elif clazz == QgsProcessingParameterNumber:
                if len(params) > 2:
                    try:
                        params[2] = Qgis.ProcessingNumberParameterType(int(params[2]))
                    except ValueError:
                        params[2] = getattr(QgsProcessingParameterNumber, params[2].split(".")[1])
                if len(params) > 3:
                    params[3] = float(params[3].strip()) if params[3] is not None else None
                if len(params) > 4:
                    params[4] = True if params[4].lower() == 'true' else False
                if len(params) > 5:
                    params[5] = float(params[5].strip()) if params[5] is not None else -sys.float_info.max + 1
                if len(params) > 6:
                    params[6] = float(params[6].strip()) if params[6] is not None else sys.float_info.max - 1
            elif clazz == QgsProcessingParameterString:
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
                if len(params) > 4:
                    params[4] = True if params[4].lower() == 'true' else False
            elif clazz == QgsProcessingParameterColor:
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
                if len(params) > 4:
                    params[4] = True if params[4].lower() == 'true' else False
            elif clazz == QgsProcessingParameterFileDestination:
                if len(params) > 4:
                    params[4] = True if params[4].lower() == 'true' else False
                if len(params) > 5:
                    params[5] = True if params[5].lower() == 'true' else False
            elif clazz == QgsProcessingParameterFolderDestination:
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
                if len(params) > 4:
                    params[4] = True if params[4].lower() == 'true' else False
            elif clazz == QgsProcessingParameterRasterDestination:
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
                if len(params) > 4:
                    params[4] = True if params[4].lower() == 'true' else False
            elif clazz == QgsProcessingParameterPointCloudDestination:
                print(params)
                if len(params) > 3:
                    params[3] = True if params[3].lower() == 'true' else False
                if len(params) > 4:
                    params[4] = True if params[4].lower() == 'true' else False
            elif clazz == QgsProcessingParameterVectorDestination:
                if len(params) > 2:
                    try:
                        params[2] = Qgis.ProcessingSourceType(int(params[2]))
                    except ValueError:
                        params[2] = getattr(QgsProcessing, params[2].split(".")[1])
                if len(params) > 4:
                    params[4] = True if params[4].lower() == 'true' else False
                if len(params) > 5:
                    params[5] = True if params[5].lower() == 'true' else False

            param = clazz(*params)
            if isAdvanced:
                param.setFlags(param.flags() | QgsProcessingParameterDefinition.Flag.FlagAdvanced)

            param.setDescription(QCoreApplication.translate(context, param.description()))

            return param
        else:
            return None
    else:  # try script syntax

        # try native method
        param = QgsProcessingParameters.parameterFromScriptCode(s)
        if param:
            return param
